Thread: [Boost ASIO/TCP] Oddity with tcp::iostream available bytes count

  1. #1
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229

    [Boost ASIO/TCP] Oddity with tcp::iostream available bytes count

    Hello,

    I am trying to use Boost's tcp::iostream, but it seems like there's something weird going on with peeking + reading.

    Here is the minimum reproducing code -
    server.cpp -
    Code:
    #include <iostream>
    #include <boost/asio.hpp>
    
    int main()
    {	
    	boost::asio::io_service io_service;
    		
    	boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 9858);
    	boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);
    		
    	boost::asio::ip::tcp::iostream *stream = new boost::asio::ip::tcp::iostream;
    	boost::system::error_code ec;
    	acceptor.accept(*(stream->rdbuf()), ec); // checked ec, this succeeds
    	
    	while (!stream->rdbuf()->available()) {}
    	
    	std::cout << "bytes available: " << stream->rdbuf()->available() << std::endl;
    	
    	char buf[5];
    	stream->read(buf, 5);
    	
    	std::cout << "bytes available: " << stream->rdbuf()->available() << std::endl;
    }
    client.cpp
    Code:
    #include <iostream>
    #include <boost/asio.hpp>
    #include <boost/lexical_cast.hpp>
    
    int main()
    {		
    	boost::asio::ip::tcp::iostream *stream = new boost::asio::ip::tcp::iostream("localhost", boost::lexical_cast<std::string>(9858));
    	
    	stream->write("asdegasdgasdhawehawehfaw", 10);
    	
    	stream->flush();
    }
    Code:
    g++ server.cpp -o server -lboost_system -pthread
    g++ client.cpp -o client -lboost_system -pthread
    if you want to compile them.

    The server listens on port 9858 for a connection, accepts a connection, wait until number of bytes in read buffer goes > 0, prints number of bytes available, reads 5 bytes, and prints number of bytes available afterwards.

    The client opens a TCP connection to the server, and sends 10 bytes.

    The server output is:
    Code:
    bytes available: 10
    bytes available: 0
    I'm expecting
    Code:
    bytes available: 10
    bytes available: 5
    since only 5 bytes were read (the data read is correct).

    Can someone take a stab at what may be going on?

    Thanks!

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Wow.

    I strongly advise, for next time obviously, employing the appropriate "using namespace ???" lines.

    Also, this would, I feel strongly, be better written against a "timeout" or "wait until", using a "Boost" API, instead of this explicit loop construct.

    Also, why are you creating a new object on the heap?

    *shrug*

    Before I say this, my test showed the same behavior and poking at it with a debugger showed that all 10 bytes were read. (Of course, I'm nearly asleep so I may have misread everything.) I'm guessing that what you are seeing is the intended behavior for the code you have written.

    The question is, should you have the code you have?

    I don't know how "Boost" works, but the version of that same code written against my library would exhibit the same behavior.

    The buffer, here the `stream_buf' implementation, reads data in chunks if at least the appropriate amount, the size of the chunk, of data is available. That data, that in the chunk, is available to the owning stream object and related operations. (So, reading 5 of 10 would leave 5 available in the buffer for reading.) However, the API, the one related to the `available' method of the underlying object, reports how many bytes are available in the underlying communication channel so that the higher level functionality can know how much it can request without blocking. (So, the buffer object reads all 10 bytes, the default buffer being 1k, the reported bytes available to be read without blocking is then zero because nothing else has been communicated.) This oddity would generally be unknown to client level code as that API is designed to report that information to implementations of the buffer object. (This would be the various descendants of the buffer object, and in my own code the relevant API are `protected' so it doesn't come up.)

    Again, I don't know how "Boost" is implemented, and I also don't know that API, but I do imagine that something similar is going on with your code.

    [Edit]
    I think a tiny bit of code may explain that last bit better.
    Code:
    // ...
    size_type available()
    {
    // ...
        count = getavailable(this->native_socket);
    // ...
    }
    // ...
    [/Edit]

    Soma

  3. #3
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    Oh yeah, I know to use timeouts, etc. This is just simplified to demonstrate the issue.

    The buffer, here the `stream_buf' implementation, reads data in chunks if at least the appropriate amount, the size of the chunk, of data is available. That data, that in the chunk, is available to the owning stream object and related operations. (So, reading 5 of 10 would leave 5 available in the buffer for reading.) However, the API, the one related to the `available' method of the underlying object, reports how many bytes are available in the underlying communication channel so that the higher level functionality can know how much it can request without blocking. (So, the buffer object reads all 10 bytes, the default buffer being 1k, the reported bytes available to be read without blocking is then zero because nothing else has been communicated.) This oddity would generally be unknown to client level code as that API is designed to report that information to implementations of the buffer object. (This would be the various descendants of the buffer object, and in my own code the relevant API are `protected' so it doesn't come up.)

    Again, I don't know how "Boost" is implemented, and I also don't know that API, but I do imagine that something similar is going on with your code.
    Ah! That would make sense. I guess I'd just have to work without an "available()" function.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unsuccessful Attempt to Count Words and Bytes in a File
    By Maggie Cao in forum C Programming
    Replies: 2
    Last Post: 01-15-2013, 02:03 PM
  2. Boost Asio and asynchronous I/O
    By Elysia in forum C++ Programming
    Replies: 9
    Last Post: 06-19-2011, 07:51 PM
  3. Open a serial port asynchronously with boost asio?
    By TriKri in forum C++ Programming
    Replies: 2
    Last Post: 05-16-2010, 12:33 PM
  4. Replies: 1
    Last Post: 05-14-2010, 03:07 AM
  5. Boost ASIO
    By PetrolMan in forum C++ Programming
    Replies: 0
    Last Post: 04-10-2009, 03:24 PM